;UNIVERSIDAD DEL VALLE DE GUATEMALA
;CONSTRUCCION DE COMPILADORES
;MARTIN GUZMAN - 08041
;PROYECTO FINAL

.MODEL	LARGE
.STACK	5000h
;-----------------------------------------
.DATA

GP	DW	1 DUP(0)	; ALL GLOBAL VAR
TO_PRINT	DB	5 DUP(0), '$'	; NUMBER TO PRINT
ENTRAR	DB	0DH, 0AH, '$'

;-----------------------------------------

.CODE


;#############################################################

START	PROC	NEAR
	.STARTUP
	XOR	AX, AX
	XOR	BX, BX
	XOR	CX, CX
	XOR	DX, DX

	;--- METHOD CALL -------------------------
	PUSH	0d	;ESPACIO PARA DIRECCION DE RETORNO
	PUSH	0d	;ESPACIO PARA t2
	PUSH	0d	;ESPACIO PARA t1
	;ESPACIO PARA DATOS LOCALES - 2
	PUSH	0d
	PUSH	0d
	;ESPACIO PARA PARAMETROS - 2
	CALL	main
	;-----------------------------------------

	MOV	AH, 4Ch
	INT	21h

START	ENDP
;#############################################################


;#############################################################

PRINT	PROC	NEAR

	;--- corregir direccion ret ----
	POP	DX
	MOV	BX, SP
	MOV	[SS:BX+2], DX
	;-------------------------------

	MOV	BX, SP
	MOV	BX, [SS:BX+0]

	MOV	DL, 10d
	MOV	CX, 5d
	MOV	DI, 4d
PRI$1:
	XOR	AX, AX
	MOV	AX, BX
	DIV	DL

	ADD	AH, 48d
	MOV	[TO_PRINT+DI], AH
	XOR	AH, AH
	MOV	BX, AX
	ADD	BX, 0d
	JZ	PRI$2
	DEC	DI
	LOOP	PRI$1
PRI$2:
	LEA	DX, [TO_PRINT+DI]

	MOV	AH, 09h
	INT	21H

	LEA	DX, [ENTRAR]

	MOV	AH, 09h
	INT	21H

;POP DEL REGISTRO DE ACTIVACION
	POP	DX
	RET
PRINT	ENDP
;#############################################################




;#############################################################
;Method: main
;	params - 0
;	Local Data - 4
;	Temporal - 4
;	Dir ret - 2
;	Val ret - void - 0
;#############################################################
main	PROC	NEAR

	;--------------------------
	POP	DX
	MOV	DI, SP
	MOV	[SS:DI+8], DX
	;--------------------------

;--- <assign> ----------------------------
	MOV	DX, 1	;DX <- 1
	MOV	CX, 0	;CX <- 0
	SUB	CX, DX
	MOV	[SS:DI+4], CX	;t$_1 <- CX
	MOV	AX, [SS:DI+4]	;AX <- t$_1
	MOV	GP[0], AX	;global[0] <- AX
;-----------------------------------------
	MOV	AX, GP[0]	;AX <- global[0]
	MOV	[SS:DI+4], AX	;t$_1 <- AX
	;--- MethodCall - print ------------------
	PUSH	0d	;for the return dir
	; local data space - 0
	; parameters space - 1
	MOV	DX, [SS:DI+4]	;DX <- t$_1
	PUSH	DX	;param temporal - print - 1

	CALL	print
	MOV	DI, SP	;return DI to this method
	;--- methodCall end - print --------------
;--- <assign> ----------------------------
	MOV	AX, 3	;AX <- 3
	MOV	GP[0], AX	;global[0] <- AX
;-----------------------------------------
;--- <assign> ----------------------------
	MOV	AX, GP[0]	;AX <- global[0]
	MOV	[SS:DI+6], AX	;t$_2 <- AX
	;--- MethodCall - factorial --------------
	PUSH	0d	;for the return value
	PUSH	0d	;for the return dir
	PUSH	0d	;for t$_4
	PUSH	0d	;for t$_3
	PUSH	0d	;for t$_2
	PUSH	0d	;for t$_1
	; local data space - 0
	; parameters space - 1
	MOV	DX, [SS:DI+6]	;DX <- t$_2
	PUSH	DX	;param temporal - factorial - 1

	CALL	factorial
	POP	DX	;return value
	MOV	DI, SP	;return DI to this method
	MOV	[SS:DI+4], DX	;t$_1 <- DX
	;--- methodCall end - factorial ----------
	MOV	DX, 1	;DX <- 1
	MOV	CX, [SS:DI+4]	;CX <- t$_1
	ADD	CX, DX
	MOV	[SS:DI+4], CX	;t$_1 <- CX
	MOV	AX, [SS:DI+4]	;AX <- t$_1
	MOV	[SS:DI+0], AX	;stack[0] <- AX
;-----------------------------------------
	MOV	AX, [SS:DI+0]	;AX <- stack[0]
	MOV	[SS:DI+4], AX	;t$_1 <- AX
	;--- MethodCall - print ------------------
	PUSH	0d	;for the return dir
	; local data space - 0
	; parameters space - 1
	MOV	DX, [SS:DI+4]	;DX <- t$_1
	PUSH	DX	;param temporal - print - 1

	CALL	print
	MOV	DI, SP	;return DI to this method
	;--- methodCall end - print --------------
;--- <assign> ----------------------------
	MOV	AX, 1	;AX <- 1
	MOV	[SS:DI+2], AX	;stack[2] <- AX
;-----------------------------------------
;### while (<exp>) <block> ###############
L_main_0:
	;=== <boolean exp> (and) =======
	MOV	AX, GP[0]	;AX <- global[0]
	MOV	[SS:DI+4], AX	;t$_1 <- AX
	MOV	AX, [SS:DI+4]	;AX <- t$_1
	MOV	CX, 20	;CX <- 20
	CMP	AX, CX
	JNE	L_main_4	;!=
	JMP	L_main_5
L_main_4:
	JMP	L_main_2
L_main_5:
	MOV	AX, 0	;AX <- 0
	MOV	[SS:DI+4], AX	;t$_1 <- AX
	JMP	L_main_3
L_main_2:
	MOV	AX, 1	;AX <- 1
	MOV	[SS:DI+4], AX	;t$_1 <- AX
L_main_3:
	MOV	AX, [SS:DI+2]	;AX <- stack[2]
	MOV	[SS:DI+6], AX	;t$_2 <- AX
	MOV	DX, [SS:DI+6]	;DX <- t$_2
	MOV	CX, [SS:DI+4]	;CX <- t$_1
	AND	CX, DX
	MOV	[SS:DI+4], CX	;t$_1 <- CX
	;===============================
	MOV	AX, [SS:DI+4]	;AX <- t$_1
	MOV	CX, 0	;CX <- 0
	CMP	AX, CX
	JE	L_main_6	;==
	JMP	L_main_7
L_main_6:
	JMP	L_main_1
L_main_7:
	MOV	AX, GP[0]	;AX <- global[0]
	MOV	[SS:DI+6], AX	;t$_2 <- AX
	;--- MethodCall - print ------------------
	PUSH	0d	;for the return dir
	; local data space - 0
	; parameters space - 1
	MOV	DX, [SS:DI+6]	;DX <- t$_2
	PUSH	DX	;param temporal - print - 1

	CALL	print
	MOV	DI, SP	;return DI to this method
	;--- methodCall end - print --------------
;--- <assign> ----------------------------
	MOV	AX, GP[0]	;AX <- global[0]
	MOV	[SS:DI+6], AX	;t$_2 <- AX
	MOV	DX, 1	;DX <- 1
	MOV	CX, [SS:DI+6]	;CX <- t$_2
	ADD	CX, DX
	MOV	[SS:DI+6], CX	;t$_2 <- CX
	MOV	AX, [SS:DI+6]	;AX <- t$_2
	MOV	GP[0], AX	;global[0] <- AX
;-----------------------------------------
	JMP	L_main_0
L_main_1:
;#########################################
;--- <assign> ----------------------------
	MOV	CX, 2	;CX <- 2
	MOV	AX, 1	;AX <- 1
	MUL	CX
	XOR	DX, DX
	MOV	[SS:DI+4], AX	;t$_1 <- AX
	MOV	CX, 25	;CX <- 25
	MOV	AX, 100	;AX <- 100
	XOR	DX, DX
	DIV	CX
	MOV	[SS:DI+6], AX	;t$_2 <- AX
	MOV	DX, 3	;DX <- 3
	MOV	CX, [SS:DI+6]	;CX <- t$_2
	ADD	CX, DX
	MOV	[SS:DI+6], CX	;t$_2 <- CX
	MOV	DX, [SS:DI+6]	;DX <- t$_2
	MOV	CX, [SS:DI+4]	;CX <- t$_1
	ADD	CX, DX
	MOV	[SS:DI+4], CX	;t$_1 <- CX
	MOV	CX, 4	;CX <- 4
	MOV	AX, [SS:DI+4]	;AX <- t$_1
	XOR	DX, DX
	DIV	CX
	MOV	[SS:DI+4], DX	;t$_1 <- DX
	MOV	CX, 2	;CX <- 2
	MOV	AX, 3	;AX <- 3
	MUL	CX
	XOR	DX, DX
	MOV	[SS:DI+6], AX	;t$_2 <- AX
	MOV	DX, [SS:DI+6]	;DX <- t$_2
	MOV	CX, [SS:DI+4]	;CX <- t$_1
	ADD	CX, DX
	MOV	[SS:DI+4], CX	;t$_1 <- CX
	MOV	AX, [SS:DI+4]	;AX <- t$_1
	MOV	GP[0], AX	;global[0] <- AX
;-----------------------------------------
	MOV	AX, GP[0]	;AX <- global[0]
	MOV	[SS:DI+4], AX	;t$_1 <- AX
	;--- MethodCall - print ------------------
	PUSH	0d	;for the return dir
	; local data space - 0
	; parameters space - 1
	MOV	DX, [SS:DI+4]	;DX <- t$_1
	PUSH	DX	;param temporal - print - 1

	CALL	print
	MOV	DI, SP	;return DI to this method
	;--- methodCall end - print --------------

	;--- METHOD END'S ---------
L_main_end:
	ADD	SP, 8d	;to POP
	RET
main	ENDP

;#############################################################




;#############################################################
;Method: factorial
;	params - 2
;	Local Data - 0
;	Temporal - 8
;	Dir ret - 2
;	Val ret - int - 2
;#############################################################
factorial	PROC	NEAR

	;--------------------------
	POP	DX
	MOV	DI, SP
	MOV	[SS:DI+10], DX
	;--------------------------

;### if(<exp>) <block1> else <block2> ####
	;=== <boolean exp> (or) ========
	MOV	AX, [SS:DI+0]	;AX <- stack[0]
	MOV	[SS:DI+2], AX	;t$_1 <- AX
	MOV	AX, [SS:DI+2]	;AX <- t$_1
	MOV	CX, 1	;CX <- 1
	CMP	AX, CX
	JE	L_factorial_6	;==
	JMP	L_factorial_7
L_factorial_6:
	JMP	L_factorial_2
L_factorial_7:
	MOV	AX, 0	;AX <- 0
	MOV	[SS:DI+2], AX	;t$_1 <- AX
	JMP	L_factorial_3
L_factorial_2:
	MOV	AX, 1	;AX <- 1
	MOV	[SS:DI+2], AX	;t$_1 <- AX
L_factorial_3:
	MOV	AX, [SS:DI+0]	;AX <- stack[0]
	MOV	[SS:DI+4], AX	;t$_2 <- AX
	MOV	AX, [SS:DI+4]	;AX <- t$_2
	MOV	CX, 0	;CX <- 0
	CMP	AX, CX
	JE	L_factorial_8	;==
	JMP	L_factorial_9
L_factorial_8:
	JMP	L_factorial_4
L_factorial_9:
	MOV	AX, 0	;AX <- 0
	MOV	[SS:DI+4], AX	;t$_2 <- AX
	JMP	L_factorial_5
L_factorial_4:
	MOV	AX, 1	;AX <- 1
	MOV	[SS:DI+4], AX	;t$_2 <- AX
L_factorial_5:
	MOV	DX, [SS:DI+4]	;DX <- t$_2
	MOV	CX, [SS:DI+2]	;CX <- t$_1
	OR	CX, DX
	MOV	[SS:DI+2], CX	;t$_1 <- CX
	;===============================
	MOV	AX, [SS:DI+2]	;AX <- t$_1
	MOV	CX, 0	;CX <- 0
	CMP	AX, CX
	JE	L_factorial_10	;==
	JMP	L_factorial_11
L_factorial_10:
	JMP	L_factorial_0
L_factorial_11:
;### <block1> ############################
	MOV	[SS:DI+12], WORD PTR 1	;return_dir <- 1
	JMP	L_factorial_end
	JMP	L_factorial_1
L_factorial_0:
;### <block2> - else #####################
	MOV	AX, [SS:DI+0]	;AX <- stack[0]
	MOV	[SS:DI+4], AX	;t$_2 <- AX
	MOV	AX, [SS:DI+0]	;AX <- stack[0]
	MOV	[SS:DI+8], AX	;t$_4 <- AX
	MOV	DX, 1	;DX <- 1
	MOV	CX, [SS:DI+8]	;CX <- t$_4
	SUB	CX, DX
	MOV	[SS:DI+8], CX	;t$_4 <- CX
	;--- MethodCall - factorial --------------
	PUSH	0d	;for the return value
	PUSH	0d	;for the return dir
	PUSH	0d	;for t$_4
	PUSH	0d	;for t$_3
	PUSH	0d	;for t$_2
	PUSH	0d	;for t$_1
	; local data space - 0
	; parameters space - 1
	MOV	DX, [SS:DI+8]	;DX <- t$_4
	PUSH	DX	;param temporal - factorial - 1

	CALL	factorial
	POP	DX	;return value
	MOV	DI, SP	;return DI to this method
	MOV	[SS:DI+6], DX	;t$_3 <- DX
	;--- methodCall end - factorial ----------
	MOV	CX, [SS:DI+6]	;CX <- t$_3
	MOV	AX, [SS:DI+4]	;AX <- t$_2
	MUL	CX
	XOR	DX, DX
	MOV	[SS:DI+4], AX	;t$_2 <- AX
	MOV	DX, [SS:DI+4]	;DX <- t$_2
	MOV	[SS:DI+12], DX	;return_dir <- DX
	JMP	L_factorial_end
L_factorial_1:
;#########################################

	;--- METHOD END'S ---------
L_factorial_end:
	ADD	SP, 10d	;to POP
	RET
factorial	ENDP

;#############################################################




;#############################################################
;Method: bla
;	params - 0
;	Local Data - 0
;	Temporal - 2
;	Dir ret - 2
;	Val ret - void - 0
;#############################################################
bla	PROC	NEAR

	;--------------------------
	POP	DX
	MOV	DI, SP
	MOV	[SS:DI+2], DX
	;--------------------------

;### while (<exp>) <block> ###############
L_bla_0:
	MOV	AX, GP[0]	;AX <- global[0]
	MOV	[SS:DI+0], AX	;t$_1 <- AX
	MOV	AX, 1	;AX <- 1
	MOV	CX, [SS:DI+0]	;CX <- t$_1
	CMP	AX, CX
	JE	L_bla_4	;==
	JMP	L_bla_5
L_bla_4:
	JMP	L_bla_2
L_bla_5:
	MOV	AX, 0	;AX <- 0
	MOV	[SS:DI+0], AX	;t$_1 <- AX
	JMP	L_bla_3
L_bla_2:
	MOV	AX, 1	;AX <- 1
	MOV	[SS:DI+0], AX	;t$_1 <- AX
L_bla_3:
	MOV	AX, [SS:DI+0]	;AX <- t$_1
	MOV	CX, 0	;CX <- 0
	CMP	AX, CX
	JE	L_bla_6	;==
	JMP	L_bla_7
L_bla_6:
	JMP	L_bla_1
L_bla_7:
;--- <assign> ----------------------------
	MOV	AX, 2	;AX <- 2
	MOV	GP[0], AX	;global[0] <- AX
;-----------------------------------------
	JMP	L_bla_0
L_bla_1:
;#########################################

	;--- METHOD END'S ---------
L_bla_end:
	ADD	SP, 2d	;to POP
	RET
bla	ENDP

;#############################################################



;-----------------------------------------
END	START
